#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "sys/time.h"

#define ARRAY_SIZE 8

void initMatrix(int initialValue);
void executeProblem1(int alterationNumber);
void executeProblem2(int alterationNumber);
void printInfo();

int matrice[ARRAY_SIZE][ARRAY_SIZE];
int problemNumber;
int initialValue;
int alterationNumber;

double timeStart, timeEnd, Texec;
struct timeval tp;

int main(int argc, char *argv[])
{
    if ( argc != 4 ) /* argc should be 3 for correct execution */
    {
        printf("Le programme a besoin d'arguments pour fonctionner.\nVeuillez recommencer selon la methode suivante.\n");

        printf("prog c p n\n");
        printf("c = Choix du probleme a executer (1 ou 2)\n");
        printf("p = La valeur initiale des elements de la matrice\n");
        printf("n = le nombre d'alterations\n");
    }
    else
    {
        printf("Choix: %s  \n", argv[1] );
        printf("Valeur initiale: %s  \n", argv[2] );
        printf("Nombre d'alterations: %s \n \n", argv[3] );

        problemNumber = atoi(argv[1]);
        initialValue = atoi(argv[2]);
        alterationNumber = atoi(argv[3]);

        initMatrix(initialValue);

		
		gettimeofday (&tp, NULL); // Debut du chronometre
		timeStart = (double) (tp.tv_sec) + (double) (tp.tv_usec) / 1e6;

        if(problemNumber == 1)
        {
            executeProblem1(alterationNumber);
        }
        else if(problemNumber == 2)
        {
            executeProblem2(alterationNumber);
        }
        else
        {
            printf("Le premier parametre doit etre 1 ou 2. Veuillez recommencer.\n");
            return 0;
        }
        printInfo();

    }
    return 0;
}

void initMatrix(int initialValue)
{
    int i, j;
    for ( i = 0; i < ARRAY_SIZE; i++ )
    {
        for ( j = 0; j < ARRAY_SIZE; j++ )
        {
            matrice[i][j] = initialValue;
        }
    }
}

void executeProblem1(int alterationNumber)
{
    int i, j, k;
	for( k = 1; k <= alterationNumber; k++)
	{
		for ( i = 0; i < ARRAY_SIZE; i++ )
		{
			for ( j = 0; j < ARRAY_SIZE; j++ )
			{
				int tempValue = matrice[i][j];
				usleep(1000);
				matrice[i][j] = tempValue + (i+j) * k;
			}
		}
	}
}

void executeProblem2(int alterationNumber)
{
    int i, j, k;
	
	for( k = 1; k <= alterationNumber; k++)
	{
		for ( i = 0; i < ARRAY_SIZE; i++ )
		{
			for ( j = 0; j < ARRAY_SIZE; j++ )
			{
				int tempValue = matrice[i][j];

				if(j == 0)
				{
					usleep(1000);
					matrice[i][j] = tempValue + i * k;
				}
				else
				{
					usleep(1000);
					matrice[i][j] = tempValue + matrice[i][j-1] * k;
				}
				//printf("matrice[%d][%d] = %d\n", i,j, matrice[i][j] );
			}
		}
	}
}

void printInfo()
{
	gettimeofday (&tp, NULL); // Fin du chronometre
	timeEnd = (double) (tp.tv_sec) + (double) (tp.tv_usec) / 1e6;
	Texec = timeEnd - timeStart; //Temps d'execution en secondes

    int i, j;
    for (i = 0; i < ARRAY_SIZE; i++)
	{
		for (j = 0; j < ARRAY_SIZE; j++)
		{
			printf("%d ", matrice[i][j]);
		}
		printf("\n");
	}
	printf("Execution time : %lf\n", Texec);
}
